package weworkgo

import (
	"encoding/xml"
	"errors"
	"gitee.com/microrain/weworkgo/lib/wxbizmsgcrypt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
)

type WechatTpMsgMap map[string]string
type msgMapEntry struct {
	XMLName xml.Name
	Value   string `xml:",chardata"`
}

func (m WechatTpMsgMap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
	if len(m) == 0 {
		return nil
	}

	err := e.EncodeToken(start)
	if err != nil {
		return err
	}

	for k, v := range m {
		_ = e.Encode(msgMapEntry{XMLName: xml.Name{Local: k}, Value: v})
	}
	return e.EncodeToken(start.End())
}

func (m *WechatTpMsgMap) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
	*m = WechatTpMsgMap{}
	for {
		var e msgMapEntry
		err := d.Decode(&e)
		if err == io.EOF {
			break
		} else if err != nil {
			return err
		}
		(*m)[e.XMLName.Local] = e.Value
	}
	return nil
}

func (m WechatTpMsgMap) GetValue(name string) interface{} {
	return m[name]
}
func (m *WechatTpMsgMap) SetValue(name, value string) {
	*m = WechatTpMsgMap{}
	(*m)[name] = value
	return
}

func (p *Provider) ParseWechatTpMsgMap(request *http.Request) (*WechatTpMsgMap, error) {

	body, err := ioutil.ReadAll(request.Body)
	if nil != err {
		log.Printf("Request read Body error: %s", err.Error())
		return nil, err
	}
	err = request.ParseForm()
	if nil != err {
		log.Printf("Request ParseForm error:(%s) %s", err.Error())
		return nil, err
	}
	var msgMap = new(WechatTpMsgMap)

	params := request.Form
	msgSign := params.Get("msg_signature")
	timeStamp := params.Get("timestamp")
	nonce := params.Get("nonce")
	receiverId := params.Get("corpid")
	echostr := params.Get("echostr")
	wxCpt := wxbizmsgcrypt.NewWXBizMsgCrypt(p.Config.CallbackToken, p.Config.CallbackEncodingAESKey, receiverId, 1)

	if echostr != "" { // 验证推送URL
		msg, cErr := wxCpt.VerifyURL(msgSign, timeStamp, nonce, echostr)
		if cErr != nil {
			log.Printf("ParseWechatCorpTpInfoData DecryptMsg EchoStr error:SuiteId(%s) %s", receiverId, cErr.ErrMsg)
			return nil, errors.New(cErr.ErrMsg)
		}
		log.Printf("ParseWechatCorpTpInfoData:CorpId(%s) %s", p.Config.CorpId, msg)
		msgMap.SetValue("echostr", string(msg))
		return msgMap, nil
	}

	decryptMsg, cErr := wxCpt.DecryptMsg(msgSign, timeStamp, nonce, body)
	if cErr != nil {
		log.Printf("WechatCryptor DecryptMsg EchoStr error:CorpId(%s) %s", receiverId, cErr.ErrMsg)
		return nil, errors.New(cErr.ErrMsg)
	}
	//decryptMsg, err := cryptor.DecryptMsg(msgSign, timeStamp, nonce, body)
	if nil != err {
		log.Printf("decryptWechatRequest DecryptMsg error:CorpId(%s) %s", p.Config.CorpId, err.Error())
		return nil, err
	}

	err = xml.Unmarshal(decryptMsg, msgMap)
	if nil != err {
		log.Printf("Unmarshal WechatTpMsgMap error:CorpId(%s) %s", p.Config.CorpId, err.Error())
		return nil, err
	}
	return msgMap, nil
}
